package it.niedermann.android.markdown

import android.text.Editable
import android.text.Html
import org.jsoup.Jsoup
import org.xml.sax.XMLReader
import java.util.Stack

/**
 * Adds `•` to unordered list items and a counter to ordered list items.
 * Call [.prepareTagHandling], so the default handler of [Html.fromHtml] does not prevent the handling.
 */
class ListTagHandler : Html.TagHandler {
    private val parents = Stack<String>()
    private val listItemIndex = Stack<Int>()
    override fun handleTag(opening: Boolean, tag: String, output: Editable, xmlReader: XMLReader) {
        if (X_OL == tag) {
            if (opening) {
                parents.push(X_OL)
                listItemIndex.push(1)
            } else {
                parents.pop()
                listItemIndex.pop()
            }
        } else if (X_UL == tag) {
            if (opening) {
                parents.push(X_UL)
            } else {
                parents.pop()
            }
        } else if (X_LI == tag) {
            if (X_OL == parents.peek()) {
                if (opening) {
                    output.append("\n")
                    for (nestingLevel in 1 until parents.size) {
                        output.append("\t\t")
                    }
                    output.append(listItemIndex.peek().toString()).append(". ")
                    listItemIndex.push(listItemIndex.pop() + 1)
                }
            } else if (X_UL == parents.peek()) {
                if (opening) {
                    output.append("\n")
                    for (nestingLevel in 1 until parents.size) {
                        output.append("\t\t")
                    }
                    output.append("•")
                }
            }
        }
    }

    companion object {
        private const val X_OL = "x-ol"
        private const val X_UL = "x-ul"
        private const val X_LI = "x-li"

        /**
         * Replace the list tags with custom tags to prevent them being handeled by [HtmlCompat].
         * Otherwise, all `li` tags will be replaced with [BulletSpan] which is not the
         * desired behavior of ordered list items.
         */
        @JvmStatic
        fun prepareTagHandling(html: String): String {
            val document = Jsoup.parse(html)
            document.getElementsByTag("ol").tagName(X_OL)
            document.getElementsByTag("ul").tagName(X_UL)
            document.getElementsByTag("li").tagName(X_LI)
            return document.outerHtml()
        }
    }
}